#ifndef _VIDEO_H
#define _VIDEO_H



/* Macros para acceder a la posicion de una memoria de video
 * segun se especifique para asignar o consultar el caracter o el atributo */
#define mem_xy_pos(mem, fila, col) (*((mem) + ((fila) * BYTES_PER_CELL * \
			LINE_LENGTH) + BYTES_PER_CELL * (col)))
#define mem_xy_attr(mem, fila, col)  (*((mem) + ((fila) * BYTES_PER_CELL * \
			LINE_LENGTH  ) + BYTES_PER_CELL * (col) + 1))
#define mem_pos(mem, x) ( *( (mem) + BYTES_PER_CELL * (x)) )
#define mem_attr(mem, x)  ( *((mem) + (BYTES_PER_CELL * (x)) + 1 ))


#define mem_video ((char *)0xb8000)

/* Atributo de video: letras blancas, fondo negro */
#define WHITE_TXT 0x07

/* Cantidad de caracteres que se pueden presentar n una linea */
#define LINE_LENGTH 80

/* Cantidad de bytes que se utilizan para representar una celda en la
 * memoria de video.  */
#define BYTES_PER_CELL 2

/* Cantidad de lineas que se pueden presentar simultanamente en la memoria de
 * video */
#define LINES_COUNT 25

/* Ultima linea en la que se puede escribir (debido a la barra de procesos)*/
#define LAST_LINE (LINES_COUNT - 2)

#define SCREEN_SIZE (LINE_LENGTH * BYTES_PER_CELL * LINES_COUNT)
#define SCREEN_USE_SIZE (LINE_LENGTH * BYTES_PER_CELL * LAST_LINE)



#define SECOND 5
#define MINUTE 4
#define HOUR 3
#define YEAR 2
#define MONTH 1
#define DAY 0
#define DATE_LENGTH 6


/*
 * Tipo de datos: videoT
 * ---------------------
 */
typedef struct{
	char mem[LINE_LENGTH * LINES_COUNT * BYTES_PER_CELL];
	unsigned int cursor;
	int active;
} videoT;


/* Prototipos de las funciones de interfaz */

/*
 * Funcion: new_video
 * ------------------
 * Se encarga de generar la estructura que controla el video. Para ello,
 * recibe como primer parametro un puntero a char que referencua una zona
 * de video auxiliar que es utilizada cuando no sE puede escribir en la
 * memoria de video (por ejemplo cuando la terminal no esta visible pero tiene
 * un proceso ejecutando que muestra algo en video). El segundo parametro en
 * caso de que sea % 2 = 0 indica que se utilizara por el momento la memoria de
 * video como salida y en caso de que sea % 2 = 1 indica que se utilizara la
 * zona de video auxiliar como salida. El ultimo argumento indica cuanto margen
 * izquierdo se debe dejar. Esto es clave para el manejo de las flechas (en
 * particular la izquierda).
 */
void init_video(videoT *v, unsigned int cursor, int active);

/*
 * Funcion: swith_video_mem
 * ------------------------
 * Esta funcion debe ser utilizada cuando se requiere intercambiar el display
 * que se esta utilizando. Generalmente sera utilizada cuando se intercambie
 * de terminal.
 */
void switch_video(videoT *v);

/*
 * Funcion set_primary_video_mem
 * -----------------------------
 * En caso de ser necesario cambia la memoria actual de video a la primaria
 * (0x8b000).
 */
void enable_video(videoT *v);

/*
 * Funcion: write_video
 * --------------------
 */
void write_video(videoT *v, char key, char attr);

/*
 * Funciones: get_cursor_pos, set_cursor_pos
 * -----------------------------------------
 * Se encargan de consultar y setear respectivamente el valor del cursor de
 * la estructura videoT.
 */
unsigned int get_cursor_pos(videoT *v);

/*
 * Funcion: set_cursor_pos
 * -----------------------
 * Setea la posicion del cursor en el video que se le envia.
 */
void set_cursor_pos(videoT *v, unsigned int cursor);

/*
 * Funcion: get_active_mem_video
 * -----------------------------
 */
char *get_active_mem_video(videoT *v);


/*
 * Funcion: set_secondary_video_mem
 * -------------------------------
 * En caso de ser necesario cambia la memoria actual de video a la secundaria.
 */
void disable_video(videoT *v);

/*
 * Funcion: clear_screen
 * ---------------------
 * Esta funcion se encarga de limpiar la memoria del actual display.
 */
void clear_screen(videoT *v);

/*
 * Funcion: clear_line
 * -------------------
 * Esta funcion es utilizada cuando es necesario borrar una linea del actual
 * display.
 */
void clear_line(videoT *v, unsigned int i);


/*
 * Funcion: clear_cell
 * -------------------
 * Se encarga de borrar la celda indicada del actual display
 */
void clear_cell(videoT *v, unsigned int row, unsigned int column);

/*
 * Funcion: scroll_screen
 * ----------------------
 * Esta funcion se encarga de deslizar la pantalla hacia arriba.
 */
void scroll_screen(videoT *v);

/*
 * Funcion: next_line
 * ------------------
 * Esta funcion se encarga de avanzar una linea en la memoria del display actual.
 * Se debe validar previamente que no sea la ultima linea ya que en dicho caso
 * se debe scrollear la pantalla antes.
 */
void next_line(videoT *v);

/*
 * Funcion: save_screen
 * --------------------
 * Guarda el display actual en una zona de memoria auxiliar.
 */
void save_screen(videoT *v);

/*
 * Funcion: restore_screen
 * -----------------------
 * Restaura la memoria del display actual a partir de la zona de memoria
 * auxiliar.
 */
void restore_screen(videoT *v);

/*
 * Funcion: set_cursor
 * -------------------
 * Setea el atributo correspondiente en la celda en que que se encuentra el
 * cursor para poder verlo.
 */
void set_cursor(videoT *v);

/*
 * Funcion: unset_cursor
 * ---------------------
 * Oculta el cursor.
 */
void unset_cursor(videoT *v);

/*
 * Funcion: clock
 * --------------
 * Imprime la fecha y hora en la esquina inferior izquierda de la pantalla.
 */
int clock(int argc, char *argv[]);

#endif /* _VIDEO_H */

